﻿using System;
using System.Collections.Generic;
using System.Text;
using KSS.Generator.Schema;
using KSS.Generator.Configuration;
using System.IO;

namespace KSS.Generator
{
    public class SqlMapperProjectGenerator : ProjectGenerator
    {
        public override string ProjectName
        {
            get { return Template.Project.SqlMapperProjectName; }
        }

        protected override void GenerateFile(ProjectSetting projectConfig, FileInfo templateFile, DirectoryInfo generatedDirectory)
        {
            switch (templateFile.Name)
            {
                case Template.SqlMapperProject.GeneratedMapperFileName:
                    GenerateMapperFile(projectConfig, templateFile, generatedDirectory);
                    break;

                case Template.SqlMapperProject.CustomMapperFileName:
                    GenerateCustomMapperFile(projectConfig, templateFile, generatedDirectory);
                    break;

                case Template.SqlMapperProject.GeneratedStoreMapperFileName:
                    GenerateStoredProcMapperFile(projectConfig, templateFile, generatedDirectory);
                    break;

                case Template.SqlMapperProject.CustomStoreMapperFileName:
                    GenerateCustomStoredProcMapperFile(projectConfig, templateFile, generatedDirectory);
                    break;
            }
        }

        private void GenerateMapperFile(ProjectSetting projectConfig, FileInfo templateFile, DirectoryInfo generatedDirectory)
        {
            // Get entity mapper template file content
            string templateContent = GeneratorHelper.ReadFromFile(templateFile.FullName);

            // Mapper file name template
            string fileNameFormat = GeneratorHelper.GetFileNameFromat(templateFile.Name);

            // Fill methods to template
            foreach (Table t in Context.DatabaseSchema.Tables)
            {
                #region { Entity name custom tag }

                projectConfig.SetPropertyValue(Template.SqlMapperProject.CustomTag_EntityName, t.DataType.Name);
                #endregion

                #region { Entity reader mapping custom tag }

                StringBuilder sbEntityReaderMapping = new StringBuilder();

                // generate assignment command
                foreach (Column c in t.DataType.Columns)
                {
                    sbEntityReaderMapping.Append(string.Format(
                                    Template.SqlMapperProject.ReaderMapping,
                                    c.Name,
                                    GeneratorHelper.GetTypeFromColumn(c)));
                }

                // set value for entity mapping property
                projectConfig.SetPropertyValue(
                                    Template.SqlMapperProject.CustomTag_EntityReaderMapping,
                                    sbEntityReaderMapping.ToString());
                #endregion

                #region { Entity row mapping custom tag }

                StringBuilder sbEntityRowMapping = new StringBuilder();

                // generate assignment command
                foreach (Column c in t.DataType.Columns)
                {
                    sbEntityRowMapping.Append(string.Format(
                                    Template.SqlMapperProject.RowMapping,
                                    c.Name,
                                    GeneratorHelper.GetTypeFromColumn(c)));
                }

                projectConfig.SetPropertyValue(
                                    Template.SqlMapperProject.CustomTag_EntityRowMapping,
                                    sbEntityRowMapping.ToString());
                #endregion

                // Fill property in template                
                string sourceCode = GeneratorHelper.FillProperties(projectConfig, templateContent);

                // Write source code to file
                string generatedFilePath = string.Format("{0}\\{1}",
                            generatedDirectory.FullName,
                            string.Format(fileNameFormat, t.DataType.Name));

                GeneratorHelper.WriteToFile(generatedFilePath, sourceCode);
            }
        }

        private void GenerateCustomMapperFile(ProjectSetting projectConfig, FileInfo templateFile, DirectoryInfo generatedDirectory)
        {
            // Get entity mapper template file content
            string templateContent = GeneratorHelper.ReadFromFile(templateFile.FullName);

            // Mapper file name template
            string fileNameFormat = GeneratorHelper.GetFileNameFromat(templateFile.Name);

            // Fill methods to template
            foreach (Table t in Context.DatabaseSchema.Tables)
            {
                #region { Entity name custom tag }

                projectConfig.SetPropertyValue(Template.SqlMapperProject.CustomTag_EntityName, t.DataType.Name);
                #endregion

                // Fill property in template                
                string sourceCode = GeneratorHelper.FillProperties(projectConfig, templateContent);

                // Write source code to file
                string generatedFilePath = string.Format("{0}\\{1}",
                            generatedDirectory.FullName,
                            string.Format(fileNameFormat, t.DataType.Name));

                GeneratorHelper.WriteToFile(generatedFilePath, sourceCode);
            }
        }

        private void GenerateStoredProcMapperFile(ProjectSetting projectConfig, FileInfo templateFile, DirectoryInfo generatedDirectory)
        {
            // Get entity mapper template file content
            string templateContent = GeneratorHelper.ReadFromFile(templateFile.FullName);

            // Mapper file name template
            string fileNameFormat = GeneratorHelper.GetFileNameFromat(templateFile.Name);

            // Fill methods to template
            foreach (Function f in Context.DatabaseSchema.Functions)
            {
                if (f.ElementType == null || string.IsNullOrEmpty(f.ElementType.Name))
                {
                    continue;
                }

                #region { Entity name custom tag }

                projectConfig.SetPropertyValue(Template.SqlMapperProject.CustomTag_EntityName, f.ElementType.Name);
                #endregion

                #region { Entity reader mapping custom tag }

                StringBuilder sbEntityReaderMapping = new StringBuilder();

                // generate assignment command
                foreach (Column c in f.ElementType.Columns)
                {
                    sbEntityReaderMapping.Append(string.Format(
                                    Template.SqlMapperProject.ReaderMapping,
                                    c.Name,
                                    GeneratorHelper.GetTypeFromColumn(c)));
                }

                // set value for entity mapping property
                projectConfig.SetPropertyValue(
                                    Template.SqlMapperProject.CustomTag_EntityReaderMapping,
                                    sbEntityReaderMapping.ToString());
                #endregion

                #region { Entity row mapping custom tag }

                StringBuilder sbEntityRowMapping = new StringBuilder();

                // generate assignment command
                foreach (Column c in f.ElementType.Columns)
                {
                    sbEntityRowMapping.Append(string.Format(
                                    Template.SqlMapperProject.RowMapping,
                                    c.Name,
                                    GeneratorHelper.GetTypeFromColumn(c)));
                }

                projectConfig.SetPropertyValue(
                                    Template.SqlMapperProject.CustomTag_EntityRowMapping,
                                    sbEntityRowMapping.ToString());
                #endregion

                // Fill property in template                
                string sourceCode = GeneratorHelper.FillProperties(projectConfig, templateContent);

                // Write source code to file
                string generatedFilePath = string.Format("{0}\\{1}",
                            generatedDirectory.FullName,
                            string.Format(fileNameFormat, f.ElementType.Name));

                GeneratorHelper.WriteToFile(generatedFilePath, sourceCode);
            }
        }

        private void GenerateCustomStoredProcMapperFile(ProjectSetting projectConfig, FileInfo templateFile, DirectoryInfo generatedDirectory)
        {
            // Get entity mapper template file content
            string templateContent = GeneratorHelper.ReadFromFile(templateFile.FullName);

            // Mapper file name template
            string fileNameFormat = GeneratorHelper.GetFileNameFromat(templateFile.Name);

            // Fill methods to template
            foreach (Function f in Context.DatabaseSchema.Functions)
            {
                if (f.ElementType == null || string.IsNullOrEmpty(f.ElementType.Name))
                {
                    continue;
                }

                #region { Entity name custom tag }

                projectConfig.SetPropertyValue(Template.SqlMapperProject.CustomTag_EntityName, f.ElementType.Name);
                #endregion

                // Fill property in template                
                string sourceCode = GeneratorHelper.FillProperties(projectConfig, templateContent);

                // Write source code to file
                string generatedFilePath = string.Format("{0}\\{1}",
                            generatedDirectory.FullName,
                            string.Format(fileNameFormat, f.ElementType.Name));

                GeneratorHelper.WriteToFile(generatedFilePath, sourceCode);
            }
        }
    }
}
